package com.xinting.piano.app;

import android.app.Activity;
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.text.TextUtils;
import android.util.Log;

import com.squareup.okhttp.Response;
import com.xinting.piano.R;
import com.xinting.piano.data.PApp;
import com.xinting.piano.lib.network.PNetWork;
import com.xinting.piano.lib.storage.PSharePreferences;
import com.xinting.piano.lib.util.PUtil;
import com.xinting.piano.service.PAccount;
import com.xinting.piano.service.PBaseCookieStore;
import com.xinting.piano.service.PBroadcast;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by wuxinting on 15/11/13.
 * 应用实例
 */
public class PApplication extends Application {

    public static String LOG_TAG = PApp.LOG_TAG+"_application";
    public static String URL_UPGRADE = "app/upgrade";
    public static String URL_ANNOUNCE = "app/announce";

    public static String KEY_ANNOUNCE_ID = "announce_id";

    /**
     * 显示toast等UI
     */
    private RoutineHandler handler;

    @Override
    public void onCreate() {
        super.onCreate();

        PApp.setAppContext(this);
        PNetWork.getInstance().enableCookie(new PBaseCookieStore(this));

        handler = new RoutineHandler();

        Intent intent = new Intent();
        intent.setClass(this, PRoutineService.class);
        bindService(intent, new BindRoutineServiceConn(), Context.BIND_AUTO_CREATE);

        //如果token无效，自动跳转到登录
        PBroadcast.getInstance().register(PApp.BC_ACCOUNT_INVALID_TOKEN, new PBroadcast.IListener() {
            @Override
            public void listen(Object data) {
                Log.d(LOG_TAG, "Jump from application to apply&login");
                Intent intent1 = new Intent();
                intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent1.setClass(PApp.getAppContext(), PApplyLoginActivity.class);
                startActivity(intent1);

                // remove account task
                PAccount.getInstance().removeRoutine();
            }
        });

        //通用socket error处理，业务层发广播
        PBroadcast.getInstance().register(PApp.BC_NETWORK_ERROR, new PBroadcast.IListener() {
            @Override
            public void listen(Object data) {
                handler.sendEmptyMessage(handler.WHAT_NETWORK_ERROR);
            }
        });
    }

    /**
     * handler of ui
     */
    private class RoutineHandler extends Handler {

        public final int WHAT_NETWORK_ERROR = 0;

        public RoutineHandler() {
            super(Looper.getMainLooper());
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case WHAT_NETWORK_ERROR:
                    PUtil.toast(PApp.getAppContext(), getResources().getString(R.string.network_error));
                    break;
            }
            super.handleMessage(msg);
        }
    }

    /**
     * 绑定日常任务服务的连接
     */
    private class BindRoutineServiceConn implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Messenger service = new Messenger(iBinder);

            /**
             * 在此处加上日常任务
             */
            //登录日常
            PAccount.getInstance().addRoutine(service);

            /**
             * 获取最新的版本
             */
            Message msg = Message.obtain(null, PRoutineService.MSG_ADD_ROUTINE_TASK);
            msg.obj = new UpgradeRoutine();

            Message msgAnnounce = Message.obtain(null, PRoutineService.MSG_ADD_ROUTINE_TASK);
            msgAnnounce.obj = new AnnounceRoutine();

            try {
                service.send(msg);
                service.send(msgAnnounce);
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Add Routine " + e.toString());
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    }

    /**
     * 获取新的系统公告
     */
    private class AnnounceRoutine implements PRoutineService.IRoutineTask {

        private Messenger service;

        @Override
        public int getId() {
            return PApp.ROUTINE_ANNOUNCE;
        }

        @Override
        public long getDelay() {
            return 0;
        }

        @Override
        public long getPeriod() {
            return -1;
        }

        @Override
        public void setMessenger(Messenger messenger) {
            service = messenger;
        }

        /**
         * 获取公告通知
         * @param content 公告内容
         * @return
         */
        private Notification getAnnounceNotification(String content) {
            Intent intent = new Intent(PApp.getAppContext(), PAnnounceActivity.class);
            intent.putExtra(PApp.KEY_CONTENT, content);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

            PendingIntent pendingIntent = PendingIntent.getActivity(PApp.getAppContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

            Resources r = PApp.getAppContext().getResources();
            String notifyContent = content;
            if (notifyContent.length() > 50) {
                notifyContent = notifyContent.substring(0, 50) + "..";
            }
            NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(PApp.getAppContext())
                    .setSmallIcon(R.mipmap.piano_notify)
                    .setContentTitle(r.getString(R.string.announce_notify_title))
                    .setContentText(notifyContent)
                    .setTicker(r.getString(R.string.announce_notify_ticker))
                    .setContentIntent(pendingIntent)
                    .setAutoCancel(true)
                    .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_LIGHTS);
            return nBuilder.build();
        }

        @Override
        public void run() {
            PSharePreferences sharePreferences = new PSharePreferences(PApp.getAppContext());
            Integer last = sharePreferences.get(KEY_ANNOUNCE_ID, 0);

            Log.v(LOG_TAG, "Announce "+last);

            try {
                Response response = PNetWork.getInstance().getSync(PUtil.joinURL(PApp.URL_SERVER, URL_ANNOUNCE) + "?last=" + last, null);
                String res = response.body().string();
                Log.v(LOG_TAG, res);

                JSONObject json = new JSONObject(res);

                int code = json.getInt(PApp.ERR_CODE);
                if (code == PApp.ERR_SUCCESS) {
                    //保存最新的公告id
                    int codeId = json.optInt(PApp.KEY_ID, 0);
                    sharePreferences.save(KEY_ANNOUNCE_ID, codeId);

                    String content = json.getString(PApp.KEY_CONTENT);
                    Message msg = Message.obtain(null, PRoutineService.MSG_NOTIFY);
                    msg.obj = getAnnounceNotification(content);
                    if (service != null) {
                        service.send(msg);
                    }
                }
            } catch (IOException e) {
                Log.e(LOG_TAG, "Get Announce " + e.toString());
            } catch (JSONException e) {
                Log.e(LOG_TAG, "Get Announce Json " + e.toString());
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Announce Send " + e.toString());
            } catch (Exception e) {
                Log.e(LOG_TAG, "Announce unknown " + e.toString());
            }
        }
    }

    /**
     * 是否有新的更新
     */
    private class UpgradeRoutine implements PRoutineService.IRoutineTask {

        private Messenger service;

        @Override
        public int getId() {
            return PApp.ROUTINE_UPGRADE;
        }

        @Override
        public long getDelay() {
            return 0;
        }

        @Override
        public long getPeriod() {
            return -1;
        }

        @Override
        public void setMessenger(Messenger messenger) {
            service = messenger;
        }

        /**
         * notify new version
         * @param version
         * @param url
         * @return
         */
        private Notification getVersionNotification(String version, String url) {
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));

            PendingIntent pendingIntent = PendingIntent.getActivity(PApp.getAppContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

            Resources r = PApp.getAppContext().getResources();
            NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(PApp.getAppContext())
                    .setSmallIcon(R.mipmap.piano_notify)
                    .setContentTitle(r.getString(R.string.upgrade_notify_title))
                    .setContentText(r.getString(R.string.upgrade_notify_version) + version)
                    .setTicker(r.getString(R.string.upgrade_notify_ticker))
                    .setContentIntent(pendingIntent)
                    .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_LIGHTS);
            return nBuilder.build();
        }

        @Override
        public void run() {
            try {
                Response response = PNetWork.getInstance().getSync(PUtil.joinURL(PApp.URL_SERVER, URL_UPGRADE), null);
                String rs = response.body().string();
                Log.v(LOG_TAG, rs);
                JSONObject json = new JSONObject(rs);

                int code = json.optInt(PApp.ERR_CODE, PApp.ERR_UNKNOWN);
                if (code != PApp.ERR_SUCCESS) {
                    return;
                }

                //new version notify
                int versioncode = json.optInt(PApp.KEY_VERSIONCODE, 0);
                String version = json.optString(PApp.KEY_VERSION);
                String url = json.optString(PApp.KEY_URL);

                Log.v(LOG_TAG, version + "," + versioncode + "," + url);

                /**
                 * send notification
                 */
                PackageManager manager = PApp.getAppContext().getPackageManager();
                PackageInfo info = manager.getPackageInfo(PApp.getAppContext().getPackageName(), 0);
                if (versioncode > info.versionCode) {
                    Log.v(LOG_TAG, "current version code: "+info.versionCode);
                    Message msg = Message.obtain(null, PRoutineService.MSG_NOTIFY);
                    msg.obj = getVersionNotification(version, url);
                    if (service != null) {
                        service.send(msg);
                    }
                }
            } catch (IOException e) {
                Log.e(LOG_TAG, e.toString());
            } catch (JSONException e) {
                Log.e(LOG_TAG, e.toString());
            } catch (RemoteException e) {
                Log.e(LOG_TAG, e.toString());
            } catch (PackageManager.NameNotFoundException e) {
                Log.e(LOG_TAG, e.toString());
            }
        }
    }
}
